home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 2.toast / pc / sample code / platforms and tools / signals / ufailure.inc1.p < prev    next >
Encoding:
Text File  |  2000-09-28  |  9.2 KB  |  396 lines

  1. {------------------------------------------------------------------------------
  2. #
  3. #    Apple Macintosh Developer Technical Support
  4. #
  5. #    Exception handling for MPW Pascal, MacApp and MPW C
  6. #
  7. #    UFailure (aka Signals) - “Exceptional code, with a few exceptions.”
  8. #
  9. #    UFailure.inc1.p    -    Pascal source - the IMPLEMENTATION
  10. #
  11. #    Copyright © 1985-1988 Apple Computer, Inc.
  12. #    All rights reserved.
  13. #
  14. #    Versions:    1.00                11/88
  15. #                1.01                06/92
  16. #
  17. #    Components:    CTestSignal.c        November 1, 1988
  18. #                CTestSignal.make    November 1, 1988
  19. #                PTestSignal.p        November 1, 1988
  20. #                PTestSignal.make    November 1, 1988
  21. #                UFailure.p            November 1, 1988
  22. #                UFailure.h            November 1, 1988
  23. #                UFailure.incl.p        November 1, 1988
  24. #                UFailure.a            November 1, 1988
  25. #
  26. #    UFailure (or Signals) is a set of exception handling routines suitable for
  27. #    use with MacApp, MPW C, and MPW Pascal. It is a jazzed-up version of the MacApp
  28. #    UFailure unit. There is a set of C interfaces to it as well.
  29. #
  30. ------------------------------------------------------------------------------}
  31.  
  32.  
  33. VAR
  34.     {$PUSH}
  35.     {$Z+}    {make gTopHandler accessable to assembly code}
  36.     gTopHandler:        PFailInfo;    {linked list of failure handlers}
  37.      gInitHandler:        ProcPtr;
  38.     {$POP}
  39.  
  40.  
  41. PROCEDURE InitUFailure; EXTERNAL;
  42.     { Allocates the heap block for CatchSignals and initializes the global
  43.         variables used by the unit. }
  44.  
  45. PROCEDURE InitSignals; EXTERNAL;
  46.     { Calls InitUFailure. It also sets up the A6 for the main level of Pascal,
  47.         so it must be called from the outermost level of Pascal. }
  48.  
  49.  
  50. FUNCTION CatchSignal: INTEGER; EXTERNAL;
  51.     { Until the procedure which encloses this call returns, this will catch
  52.         subsequent Signal calls, returning the code passed to Signal.  When
  53.         CatchSignal is encountered initially, it returns a code of zero.  These
  54.         calls may "nest"; i.e. you may have multiple CatchSignals in one procedure.
  55.         Each nested CatchSignal call uses 72 bytes of heap space.
  56.         If you signal with SignalMessage and pass in a non-zero message you should use
  57.         CatchHandler instead so you have a way of getting at the message. }
  58.  
  59.  
  60. PROCEDURE FreeSignal; EXTERNAL;
  61.     { This undoes the effect of the last CatchSignal.  A Signal will then invoke
  62.         the CatchSignal prior to the last one. }
  63.  
  64.  
  65. PROCEDURE Signal(code: INTEGER); EXTERNAL;
  66.     { Returns control to the point of the last CatchSignal.  The program will
  67.         then behave as though that CatchSignal had returned with the code parameter
  68.         supplied to Signal. If CatchHandler is catching, the message parameter will be 0. }
  69.  
  70.  
  71. PROCEDURE SignalMessage(code: INTEGER; message: LONGINT); EXTERNAL;
  72.     { Returns control to the point of the last CatchSignal/CatchFailures.
  73.         If CatchFailures is catching, the message parameter will be returned. }
  74.         
  75.         
  76. {-----------------------------------+
  77. |    MacApp stuff                    |
  78. +-----------------------------------}
  79.  
  80.  
  81. {-----------------------------------+ 
  82. |    External Declarations            |
  83. +-----------------------------------}
  84. PROCEDURE CatchFailures (VAR fi: FailInfo;
  85.                         PROCEDURE Handler(e: INTEGER; m: LONGINT)); EXTERNAL;
  86.  
  87. PROCEDURE DoFailure(pf: PFailInfo); EXTERNAL;
  88.  
  89. {-----------------------------------+ 
  90. |    CallInitHandler                    |
  91. +-----------------------------------}
  92. PROCEDURE CallInitHandler (error: INTEGER; message: LONGINT; p: ProcPtr);
  93.         INLINE    $205F,        {MOVE.L        (A7)+,A0    }
  94.                 $4E90;        {JMP        (A0)        }
  95.  
  96. {$IFC UsingMacApp}
  97. {$S MAMain}
  98. {$ENDC}
  99. {-----------------------------------+ 
  100. |    FailMemError                    |
  101. +-----------------------------------}
  102. PROCEDURE FailMemError;
  103. VAR
  104.     e:    OSErr;
  105. {$IFC qDebug}
  106.     s:        Str255;
  107. {$ENDC}
  108. BEGIN
  109.     e := MemError;
  110.  
  111. {$IFC UsingMacApp}
  112. {$IFC qDebug}
  113.     IF gAskFailure AND (e = noErr) AND CanReadLn THEN
  114.         BEGIN
  115. {$%+}
  116.         GetMethodName(%_GetA6+4, s);
  117. {$%-}
  118.         e := ReadInteger(CONCAT('FailMemError called by ', s, '.  Enter return error: '));
  119.         END;
  120. {$ENDC qDebug}
  121. {$ENDC UsingMacApp}
  122.  
  123.     IF e <> noErr THEN
  124.         Failure(e, 0);
  125. END {FailMemError};
  126.  
  127.  
  128. {$IFC UsingMacApp}
  129. {$S MAMain}
  130. {$ENDC}
  131. {-----------------------------------+ 
  132. |    FailNIL                            |
  133. +-----------------------------------}
  134. PROCEDURE FailNIL (p: UNIV Ptr);
  135. BEGIN
  136.     { no check for gAskFailure here, since we do this when objects are created. }
  137.     IF p = NIL THEN
  138.         Failure(memFullErr, 0);
  139. END {FailNIL};
  140.  
  141.  
  142. {$IFC UsingMacApp}
  143. {$S MAMain}
  144. {$ENDC}
  145. {-----------------------------------+ 
  146. |    FailNewMessage                    |
  147. +-----------------------------------}
  148. PROCEDURE FailNewMessage (error: INTEGER; oldMessage, newMessage: LONGINT);
  149. BEGIN
  150.     IF oldMessage = 0 THEN
  151.         oldMessage := newMessage;
  152.     Failure(error, oldMessage);
  153. END {FailNewMessage};
  154.  
  155.  
  156. {$IFC UsingMacApp}
  157. {$S MAMain}
  158. {$ENDC}
  159. {-----------------------------------+ 
  160. |    FailOSErr                        |
  161. +-----------------------------------}
  162. PROCEDURE FailOSErr (error: INTEGER);
  163.  
  164. {$IFC qDebug}
  165. VAR
  166.     s:        Str255;
  167. {$ENDC}
  168.  
  169. BEGIN
  170. {$IFC UsingMacApp}
  171. {$IFC qDebug}
  172.     IF gAskFailure AND (error = noErr) AND CanReadLn THEN
  173.         BEGIN
  174. {$%+}
  175.         GetMethodName(%_GetA6+4, s);
  176. {$%-}
  177.         error := ReadInteger(CONCAT('FailOSErr called by ', s, '.  Enter return error: '));
  178.         END;
  179. {$ENDC qDebug}
  180. {$ENDC UsingMacApp}
  181.  
  182.     IF error <> noErr THEN
  183.         Failure(error, 0);
  184. END {FailOSErr};
  185.  
  186.  
  187. {$IFC UsingMacApp}
  188. {$S MAMain}
  189. {$ENDC}
  190. {-----------------------------------+ 
  191. |    FailResError                    |
  192. +-----------------------------------}
  193. PROCEDURE FailResError;
  194. VAR
  195.     e:    OSErr;
  196. {$IFC qDebug}
  197.     s:        Str255;
  198. {$ENDC}
  199. BEGIN
  200.     e := ResError;
  201.  
  202. {$IFC UsingMacApp}
  203. {$IFC qDebug}
  204.     IF gAskFailure AND (e = noErr) AND CanReadLn THEN
  205.         BEGIN
  206. {$%+}
  207.         GetMethodName(%_GetA6+4, s);
  208. {$%-}
  209.         e := ReadInteger(CONCAT('FailResError called by ', s, '.  Enter return error: '));
  210.         END;
  211. {$ENDC qDebug}
  212. {$ENDC UsingMacApp}
  213.  
  214.     IF e <> noErr THEN
  215.         Failure(e, 0);
  216. END {FailResError};
  217.  
  218.  
  219. {$IFC UsingMacApp}
  220. {$S MAMain}
  221. {$ENDC}
  222. {-----------------------------------+ 
  223. |    Failure                            |
  224. +-----------------------------------}
  225. PROCEDURE Failure (error: INTEGER; message: LONGINT);
  226. VAR
  227.     pf:     PFailInfo;
  228.     ih:     ProcPtr;
  229.     pc:        LONGINT;
  230. {$IFC UsingMacApp}
  231. {$IFC qDebug}
  232.     cl:     String8;
  233.     me:     String8;
  234.     seg:    INTEGER;
  235.     who:    STRING[17];
  236. {$ENDC qDebug}
  237. {$ENDC UsingMacApp}
  238. BEGIN
  239.     pf := gTopHandler;
  240.  
  241.     IF pf <> NIL THEN
  242.         BEGIN
  243. {$IFC UsingMacApp}
  244. {$IFC qDebug}
  245.         pc := pf^.whoPC;
  246.         GetProcname(LONGINT(@pc), cl, me);
  247.         who := CONCAT(cl, '.', me);
  248.         IF cl = kSpace8 THEN
  249.             who[9] := ' ';
  250.         
  251.         Writeln('Failure caught by ', who);
  252.         Writeln('        error = ', error:1, ' message = ', message:1,
  253.                 ' (', BSR(message, 16):1, '/', BAND(message, $0000FFFF):1, ')');
  254. {$ENDC qDebug}
  255. {$ENDC UsingMacApp}
  256.  
  257.     {* RBB removed the line 
  258.         gTopHandler := pf^.nextInfo;
  259.       on 9/26/88 since DoFailure calls FreeSignal first thing *}
  260.         pf^.error := error;
  261.         pf^.message := message;
  262.         DoFailure(pf);            {Go execute the failure handler}
  263.         END
  264.     ELSE IF gInitHandler <> NIL THEN
  265.         BEGIN
  266.         ih := gInitHandler;
  267.         gInitHandler := NIL;
  268.         CallInitHandler(error, message, ih);
  269.  
  270.         ExitToShell;
  271.         END
  272.     ELSE
  273.         BEGIN
  274. {$IFC UsingMacApp}
  275. {$IFC qDebug}
  276.         ProgramBreak('Failure called, but no handler!');
  277. {$ENDC qDebug}
  278. {$ELSEC}
  279.     Debugger;
  280. {$ENDC UsingMacApp}
  281.         END;
  282. END {Failure};
  283.  
  284.  
  285. {$IFC UsingMacApp}
  286. {$IFC qDebug}
  287. {$IFC qTrace}{$D+}{$ENDC}
  288. {$S MADebug}
  289. {-----------------------------------+ 
  290. |    ProgramBreak                    |
  291. +-----------------------------------}
  292. PROCEDURE ProgramBreak (grievance: Str255);
  293.     { ProgramBreak: Your app can call this when it comes to a situation that you do not expect
  294.         and cannot handle gracefully.  It beeps and displays a message.  If called before
  295.         there is a WriteLn window, it calls OBJFail, which goes into an infinite loop.
  296.         Otherwise, it enters our debugger. }
  297. VAR
  298.     synthRec:    RECORD
  299.                 mode:        INTEGER;
  300.                 triplet:    Tone;
  301.                 endTriplet: Tone;
  302.                 END;
  303.  
  304. BEGIN
  305. {$IFC FALSE}
  306.     WITH synthRec, triplet DO
  307.         BEGIN
  308.         mode := swMode;
  309.  
  310.         count := 445;
  311.         amplitude := 100;
  312.         duration := 25;
  313.  
  314.         endTriplet.count := 0;
  315.         endTriplet.amplitude := 0;
  316.         endTriplet.duration := 0;
  317.         END;
  318.  
  319.     StartSound(@synthRec, SIZEOF(synthRec), Pointer(-1));
  320. {$ENDC}
  321.     SysBeep(2);
  322.  
  323.     WWForceOutput(forceOn, forceUnchanged);
  324.     WriteLn('ProgramBreak: ', grievance);
  325.     WWEndForce;
  326.  
  327. {$IFC qTrace}
  328.     TRCBreak;
  329. {$ELSEC}
  330.     OBJFail(kFailNone);
  331. {$ENDC}
  332. END {ProgramBreak};
  333. {$IFC qTrace}{$D++}{$ENDC}
  334.  
  335.  
  336. {$IFC qTrace}{$D+}{$ENDC}
  337. {$S MADebug}
  338. {-----------------------------------+ 
  339. |    ProgramReport                    |
  340. +-----------------------------------}
  341. PROCEDURE ProgramReport (grievance: Str255; break: BOOLEAN);
  342.  
  343. BEGIN
  344.     Writeln(grievance);
  345.     IF break THEN
  346.         TRCBreak;
  347. END {ProgramReport};
  348. {$IFC qTrace}{$D++}{$ENDC}
  349. {$ENDC qDebug}
  350. {$ENDC UsingMacApp}
  351.  
  352.  
  353. {$IFC UsingMacApp}
  354. {$S MAInit}
  355. {$IFC qTrace}{$D+}{$ENDC}
  356. {-----------------------------------+ 
  357. |    SetInitHandler                    |
  358. +-----------------------------------}
  359. PROCEDURE SetInitHandler (handler: ProcPtr);
  360. BEGIN
  361.     gInitHandler := handler;
  362. END {SetInitHandler};
  363. {$IFC qTrace}{$D++}{$ENDC}
  364. {$ENDC UsingMacApp}
  365.  
  366.  
  367. {We assume that the programmer passes in the correct FailInfo record; ie. the one that is the
  368.     top of the stack.}
  369. {$IFC UsingMacApp}
  370. {$S MAMain}
  371. {$ENDC}
  372. {-----------------------------------+ 
  373. |    Success                            |
  374. +-----------------------------------}
  375. PROCEDURE Success (VAR fi: FailInfo);
  376. BEGIN
  377. {$IFC qDebug}
  378.     IF gTopHandler <> @fi THEN
  379.     {$IFC UsingMacApp}
  380.         BEGIN
  381.         Write('gTopHandler = ');
  382.         WritePtr(gTopHandler);
  383.         Write('parameter = ');
  384.         WritePtr(@fi);
  385.         WRITELN;
  386.         ProgramBreak('Problem with Success: too many or too few calls to Success');
  387.         END;
  388.     {$ELSEC UsingMacApp}
  389.         Debugger;
  390.     {$ENDC UsingMacApp}
  391. {$ENDC qDebug}
  392.  
  393.     gTopHandler := fi.nextInfo;
  394. END {Success};
  395.  
  396.